package com.kurt.service.impl;

import com.kurt.dto.SysDictTypeDTO;
import com.kurt.dto.create.SysDictTypeCreateRequest;
import com.kurt.dto.query.SysDictTypeQueryRequest;
import com.kurt.dto.update.SysDictTypeUpdateRequest;
import com.kurt.entity.SysDictType;
import com.kurt.repository.SysDictTypeRepository;
import com.kurt.service.SysDictTypeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 数据字典类型服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysDictTypeServiceImpl extends BaseServiceImpl<SysDictType, Long> implements SysDictTypeService {

    private final SysDictTypeRepository dictTypeRepository;

    @Override
    protected SysDictTypeRepository getRepository() {
        return dictTypeRepository;
    }

    @Override
    protected SysDictTypeRepository getSpecificationExecutor() {
        return dictTypeRepository;
    }

    @Override
    @Transactional
    public SysDictTypeDTO createDictType(SysDictTypeCreateRequest createRequest) {
        log.info("创建数据字典类型: {}", createRequest.getDictType());

        // 检查字典类型是否已存在
        if (dictTypeRepository.existsByDictType(createRequest.getDictType())) {
            throw new RuntimeException("字典类型已存在");
        }

        // 创建字典类型实体
        SysDictType dictType = new SysDictType();
        BeanUtils.copyProperties(createRequest, dictType);
        dictType.setCreateTime(LocalDateTime.now());
        dictType.setUpdateTime(LocalDateTime.now());
        dictType.setCreateUserId(com.kurt.util.UserContext.getUserId());
        dictType.setUpdateUserId(com.kurt.util.UserContext.getUserId());

        // 保存字典类型
        dictType = dictTypeRepository.save(dictType);

        log.info("数据字典类型创建成功: {}", dictType.getDictType());
        return convertToSysDictTypeDTO(dictType);
    }

    @Override
    @Transactional
    public SysDictTypeDTO updateDictType(SysDictTypeUpdateRequest updateRequest) {
        log.info("更新数据字典类型: {}", updateRequest.getId());

        // 查找字典类型
        SysDictType dictType = getById(updateRequest.getId());

        // 检查字典类型是否已存在（排除自己）
        if (!updateRequest.getDictType().equals(dictType.getDictType()) &&
                dictTypeRepository.existsByDictTypeAndIdNot(updateRequest.getDictType(), updateRequest.getId())) {
            throw new RuntimeException("字典类型已存在");
        }

        // 更新字典类型信息
        BeanUtils.copyProperties(updateRequest, dictType, "id", "createTime", "createUserId");
        dictType.setUpdateTime(LocalDateTime.now());
        dictType.setUpdateUserId(com.kurt.util.UserContext.getUserId());

        // 保存字典类型
        dictType = dictTypeRepository.save(dictType);

        log.info("数据字典类型更新成功: {}", dictType.getDictType());
        return convertToSysDictTypeDTO(dictType);
    }

    @Override
    public Page<SysDictTypeDTO> getDictTypePage(SysDictTypeQueryRequest queryRequest) {
        // 构建分页参数
        Sort sort = Sort.by(Sort.Direction.fromString(queryRequest.getOrderDirection()), queryRequest.getOrderBy());
        Pageable pageable = PageRequest.of(queryRequest.getPageNum() - 1, queryRequest.getPageSize(), sort);

        // 构建查询条件
        Specification<SysDictType> spec = buildDictTypeSpecification(queryRequest);

        // 执行分页查询
        Page<SysDictType> dictTypePage = dictTypeRepository.findAll(spec, pageable);

        // 转换为DTO
        return dictTypePage.map(this::convertToSysDictTypeDTO);
    }

    @Override
    public List<SysDictTypeDTO> getDictTypeList(SysDictTypeQueryRequest queryRequest) {
        // 构建查询条件
        Specification<SysDictType> spec = buildDictTypeSpecification(queryRequest);

        // 执行查询
        List<SysDictType> dictTypes = dictTypeRepository.findAll(spec);

        // 转换为DTO
        return dictTypes.stream().map(this::convertToSysDictTypeDTO).collect(Collectors.toList());
    }

    @Override
    public SysDictTypeDTO getDictTypeByType(String dictType) {
        Optional<SysDictType> dictTypeOpt = dictTypeRepository.findByDictType(dictType);
        return dictTypeOpt.map(this::convertToSysDictTypeDTO).orElse(null);
    }

    @Override
    public boolean existsByDictType(String dictType) {
        return dictTypeRepository.existsByDictType(dictType);
    }

    @Override
    public boolean existsByDictTypeAndIdNot(String dictType, Long excludeId) {
        return dictTypeRepository.existsByDictTypeAndIdNot(dictType, excludeId);
    }

    @Override
    @Transactional
    public boolean deleteDictTypes(List<Long> ids) {
        log.info("批量删除数据字典类型: {}", ids);

        for (Long id : ids) {
            dictTypeRepository.deleteById(id);
        }

        log.info("批量删除数据字典类型成功: {}", ids);
        return true;
    }

    /**
     * 构建数据字典类型查询条件
     */
    private Specification<SysDictType> buildDictTypeSpecification(SysDictTypeQueryRequest queryRequest) {
        return (root, query, cb) -> {
            List<jakarta.persistence.criteria.Predicate> predicates = new ArrayList<>();

            // 字典名称模糊查询
            if (StringUtils.hasText(queryRequest.getDictName())) {
                predicates.add(cb.like(root.get("dictName"), "%" + queryRequest.getDictName() + "%"));
            }

            // 字典类型模糊查询
            if (StringUtils.hasText(queryRequest.getDictType())) {
                predicates.add(cb.like(root.get("dictType"), "%" + queryRequest.getDictType() + "%"));
            }

            // 状态查询
            if (queryRequest.getStatus() != null) {
                predicates.add(cb.equal(root.get("status"), queryRequest.getStatus()));
            }

            // 创建时间范围查询
            if (StringUtils.hasText(queryRequest.getCreateTimeStart())) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"),
                        LocalDateTime.parse(queryRequest.getCreateTimeStart())));
            }
            if (StringUtils.hasText(queryRequest.getCreateTimeEnd())) {
                predicates.add(cb.lessThanOrEqualTo(root.get("createTime"),
                        LocalDateTime.parse(queryRequest.getCreateTimeEnd())));
            }

            return cb.and(predicates.toArray(new jakarta.persistence.criteria.Predicate[0]));
        };
    }

    /**
     * 转换数据字典类型实体为DTO
     */
    private SysDictTypeDTO convertToSysDictTypeDTO(SysDictType dictType) {
        SysDictTypeDTO dto = new SysDictTypeDTO();
        BeanUtils.copyProperties(dictType, dto);

        // 设置状态文本
        if (dictType.getStatus() != null) {
            dto.setStatusText(dictType.getStatus() == 1 ? "启用" : "禁用");
        }

        return dto;
    }
}
